/**
 * 
 */
package jmine.tec.test.proxy;

import java.util.HashMap;
import java.util.Map;

/**
 * Classe utilitaria
 * 
 * @author takeshi
 */
public final class MockObjectSupport {
    /**
     * 
     */
    private MockObjectSupport() {
        super();
    }

    private static final Map<Class<?>, Object> PRIMITIVE_VALUES = new HashMap<Class<?>, Object>();

    private static final Map<Class<?>, Class<?>> PRIMITIVE_COERCION = new HashMap<Class<?>, Class<?>>();
    static {
        PRIMITIVE_COERCION.put(double.class, Double.class);
        PRIMITIVE_COERCION.put(int.class, Integer.class);
        PRIMITIVE_COERCION.put(short.class, Short.class);
        PRIMITIVE_COERCION.put(boolean.class, Boolean.class);
        PRIMITIVE_COERCION.put(char.class, Character.class);
        PRIMITIVE_COERCION.put(long.class, Long.class);
        PRIMITIVE_COERCION.put(byte.class, Byte.class);
        PRIMITIVE_COERCION.put(float.class, Float.class);
    }

    static {
        // PRIMITIVE_VALUES.put(Boolean.class, Boolean.FALSE);
        PRIMITIVE_VALUES.put(boolean.class, Boolean.FALSE);
        // PRIMITIVE_VALUES.put(Short.class, Short.valueOf((short) 0));
        PRIMITIVE_VALUES.put(short.class, Short.valueOf((short) 0));
        // PRIMITIVE_VALUES.put(Byte.class, Byte.valueOf((byte) 0));
        PRIMITIVE_VALUES.put(byte.class, Byte.valueOf((byte) 0));
        // PRIMITIVE_VALUES.put(Character.class, Character.valueOf((char) 0));
        PRIMITIVE_VALUES.put(char.class, Character.valueOf((char) 0));
        // PRIMITIVE_VALUES.put(Float.class, 0f);
        PRIMITIVE_VALUES.put(float.class, 0f);
        // PRIMITIVE_VALUES.put(Double.class, 0.0d);
        PRIMITIVE_VALUES.put(double.class, 0.0d);
        PRIMITIVE_VALUES.put(int.class, 0);
        // PRIMITIVE_VALUES.put(Integer.class, 0);
        PRIMITIVE_VALUES.put(long.class, 0L);
        // PRIMITIVE_VALUES.put(Long.class, 0L);
    }

    /**
     * Devolve o valor padrao para um tipo. Se o tipo for primitivo, devolve o wrapper correspondente. Caso contrario, devolve
     * <code>null</code>
     * 
     * @param type o tipo
     * @return {@link Object}
     */
    public static Object getDefaultValueFor(final Class<?> type) {
        if (type.isPrimitive()) {
            return PRIMITIVE_VALUES.get(type);
        }
        return null;
    }

    /**
     * Verifica se o valor passado pode ser coercido para o tipo passado
     * 
     * @param type o tipo
     * @param value o valor
     * @return <code>true</code>
     */
    public static boolean checkCompatible(final Class<?> type, final Object value) {
        if (value == null) {
            return true;
        }
        if (type.isPrimitive()) {
            return PRIMITIVE_COERCION.get(type).isInstance(value);
        } else {
            return type.isInstance(value);
        }
    }

}
